#!/bin/bash

SCRIPT_PATH=$(cd "$(dirname "$0")" || exit; pwd)

if [[ ! -d $1 ]]; then
    BINARY=$(realpath "$1")
else
    BINARY_base=$(basename $1)
    BINARY=$(realpath $BINARY_base)
fi

ARGS="${@:2}"
SIMULATOR=""
LD_PREFIX=""
LD_PATH=""
STRINGS_FILE=$(mktemp)
FILE_INFO=$(mktemp)

trap 'rm -f ${STRINGS_FILE} ${FILE_INFO}' EXIT

check_result()
{
    ret=$1
    message=$2
    log_file=$3
    if [ "$ret" -ne 0 ]; then
        echo "$message"
        [ -f "${log_file}" ] && cat "${log_file}"
        exit 1
    fi
}

check_cmd()
{
    command -v "$1" > /dev/null 2>&1
}

need_cmd()
{
    cmd="$1"
    if ! check_cmd "${cmd}"; then
        err "need '${cmd}' (command not found) "
    fi
}

is_have_str()
{
    match_str=$1
    target_file=$2
    if [[ ! -f "${target_file}" ]]; then
        echo "${target_file} is not existed"
        exit 1
    fi
    # match return 1 otherwise return 0
    if grep -q "${match_str}" "${target_file}"; then
        return 1
    else
        return 0
    fi
}

select_simulator()
{
    # select qemu
    if [[ "${IS_AARCH64}" -eq 1 ]]; then
        SIMULATOR="qemu-aarch64"
    elif [[ "${IS_RISCV64}" -eq 1 ]]; then
        SIMULATOR="qemu-riscv64"
    elif [[ "${IS_X86}" -eq 1 ]]; then
        SIMULATOR="qemu-x86_64"
    elif [[ "${IS_MIPSEL}" -eq 1 ]]; then
        SIMULATOR="qemu-mipsel"
    elif [[ "${IS_ARM}" -eq 1 ]]; then
        SIMULATOR="qemu-arm"
    fi
 
    # check qemu
    need_cmd "${SIMULATOR}"
}

select_lib_path()
{
    # ohos
    if [[ "${IS_OHOS_COMPILER}" -eq 1 ]]; then
        if [[ "${IS_OHOS}" -eq 1 ]]; then
            if [[ "${IS_AARCH64}" -eq 1 ]]; then
                LD_PREFIX=${SCRIPT_PATH}/../../../../toolchain/sysroot/aarch64-linux-ohos/usr
                LD_PATH=${SCRIPT_PATH}/../../../../toolchain/clang-dev/lib/aarch64-linux-ohos
            elif [[ "${IS_RISCV64}" -eq 1 ]]; then
                LD_PREFIX=${SCRIPT_PATH}/../../../../toolchain/sysroot/riscv64-linux-ohos/usr
                LD_PATH=${SCRIPT_PATH}/../../../../toolchain/clang-dev/lib/riscv64-linux-ohos
            elif [[ "${IS_X86}" -eq 1 ]]; then
                LD_PREFIX=${SCRIPT_PATH}/../../../../toolchain/sysroot/x86_64-linux-ohos/usr
                LD_PATH=${SCRIPT_PATH}/../../../../toolchain/clang-dev/lib/x86_64-linux-ohos
            elif [[ "${IS_MIPSEL}" -eq 1 ]]; then
                LD_PREFIX=${SCRIPT_PATH}/../../../../toolchain/sysroot/mipsel-linux-ohos/usr
                LD_PATH=${SCRIPT_PATH}/../../../../toolchain/clang-dev/lib/mipsel-linux-ohos
            elif [[ "${IS_ARM}" -eq 1 ]]; then
                # TODO: Distinguish between arm-liteos-ohos and arm-linux-ohos
                LD_PREFIX=${SCRIPT_PATH}/../../../../toolchain/sysroot/arm-linux-ohos/usr
                LD_PATH=${SCRIPT_PATH}/../../../../toolchain/clang-dev/lib/arm-linux-ohos
            fi
        fi
        if [[ "${IS_GNU}" -eq 1 ]]; then
            LD_PREFIX="/usr/aarch64-linux-gnu"
            LD_PATH="${SCRIPT_PATH}/../../../../toolchain/clang-dev"
        fi
    fi

    # hos
    if [[ "${IS_OHOS_COMPILER}" -eq 0 ]]; then
        if [[ "${IS_AARCH64}" -eq 1 ]]; then
            LD_PREFIX="/usr/aarch64-linux-gnu"
            LD_PATH=${SCRIPT_PATH}/../../../../toolchain/linux-x86/bisheng_clang
        # TODO
        elif [[ "${IS_RISCV64}" -eq 1 ]]; then
            LD_PREFIX=""
            LD_PATH=""
        elif [[ "${IS_X86}" -eq 1 ]]; then
            LD_PREFIX=""
            LD_PATH=""
        elif [[ "${IS_MIPSEL}" -eq 1 ]]; then
            LD_PREFIX=""
            LD_PATH=""
        elif [[ "${IS_ARM}" -eq 1 ]]; then
            LD_PREFIX=""
            LD_PATH=""
        fi
    fi

    # check LD_PREFIX and LD_PATH
    if [ ! -d "${LD_PREFIX}" ];then
        echo "${LD_PREFIX} is not existed"
        exit 1
    fi
    if [ ! -d "${LD_PATH}" ];then
        echo "${LD_PATH} is not existed"
        exit 1
    fi
}

check_env()
{    
    # check input elf file
    if [ ! -e "${BINARY}" ];then
        echo "FATAL ERROR: Missing input ELF file name"
        exit 1
    fi
   
    chmod +x "${BINARY}"

    # get elf file strings
    strings "${BINARY}" >& "${STRINGS_FILE}"
    check_result $? "'strings' command has errors." "${STRINGS_FILE}"
   
    # OHOS compiler
    export IS_OHOS_COMPILER
    IS_OHOS_COMPILER=$(is_have_str "OHOS" "${STRINGS_FILE}"; echo $?)

    # ohos backend
    export IS_OHOS
    IS_OHOS=$(is_have_str "ohos" "${STRINGS_FILE}"; echo $?)

    # gnu backend
    export IS_GNU
    IS_GNU=$(is_have_str "gnu.version" "${STRINGS_FILE}"; echo $?)

    # get elf file architecture info
    file -b "${BINARY}" >& "${FILE_INFO}"
    check_result $? "'file' command has errors." "${FILE_INFO}"
   
    # aarcch64
    export IS_AARCH64
    IS_AARCH64=$(is_have_str "aarch64" "${FILE_INFO}"; echo $?)
   
    # riscv64
    export IS_RISCV64
    IS_RISCV64=$(is_have_str "riscv64" "${FILE_INFO}"; echo $?)

    # x86_64
    export IS_X86
    IS_X86=$(is_have_str "x86-64" "${FILE_INFO}"; echo $?)
   
    # mipsel
    export IS_MIPSEL
    IS_MIPSEL=$(is_have_str "MIPS" "${FILE_INFO}"; echo $?)
   
    # arm
    export IS_ARM
    IS_ARM=$(is_have_str "arm" "${FILE_INFO}"; echo $?)
}


entry()
{
    local exit_code
    check_env
    select_simulator
    select_lib_path

    ${SIMULATOR} -L "${LD_PREFIX}" -E LD_LIBRARY_PATH=${LD_PATH}:${LD_LIBRARY_PATH} "${BINARY}" ${ARGS} &> ${BINARY}_result
    exit_code=$?
    sed "/Can't connect to server. Errno: 2/d" ${BINARY}_result
    rm ${BINARY}_result
    exit ${exit_code}
}

entry
